package com.hexb.smh.service.impl;

import com.hexb.core.exception.BusinessException;
import com.hexb.core.model.BaseErrorCodes;
import com.hexb.core.utils.Assert;
import com.hexb.core.utils.ObjectUtils;
import com.hexb.smh.entity.Commission;
import com.hexb.smh.entity.view.CommissionAmount;
import com.hexb.smh.entity.view.CommissionDiscountRate;
import com.hexb.smh.entity.view.CommissionTable;
import com.hexb.smh.errors.ErrorCodes;
import com.hexb.smh.mapper.CommissionMapper;
import com.hexb.smh.service.ICommissionService;
import com.hexb.smh.utils.AccountHelper;
import com.hexb.smh.utils.POIExcelHelper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.poi.ss.usermodel.CellStyle.BORDER_THIN;

/**
 * @author : hexb
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class CommissionService implements ICommissionService {

    private static final Pattern p = Pattern.compile("([\\d.]*)([>\\-<])([\\d.]*)");

    @NonNull
    final private CommissionMapper commissionMapper;

    @Override
    public int saveOrUpdate(@NotNull Commission commission) {
        return commissionMapper.saveOrUpdate(commission);
    }

    @Override
    public int update(Commission commission) {
        Assert.isNull(commission, BaseErrorCodes.PARAMETER_IS_NULL);
        Assert.isNull(commission.getId(), BaseErrorCodes.PARAMETER_IS_NULL);
        return commissionMapper.update(commission);
    }

    @Override
    public CommissionTable<?> createEditableTable() {
        return null;
    }

    @Override
    public CommissionTable<String> createReadOnlyTable(Integer brandId) {
        CommissionTable<String> t = new CommissionTable<>();
        String ca = "a";
        String cb = "b";
        List<CommissionDiscountRate> rates = commissionMapper.getDiscountRate(brandId);
        Assert.isNull(rates, ErrorCodes.COMMISSION_NOT_IMPORTED);

        int rateLen = rates.size();
        List<String> columns = createColumns(rateLen);
        columns.add(0, cb);
        columns.add(0, ca);
        t.setColumns(columns);

        int allLen = rateLen + 2;
        //组装综合折扣最小值行
        LinkedList<Map<String, String>> data = new LinkedList<>();
        Map<String, String> minRateMap = new HashMap<>();
        for (int i = 2; i < allLen; i++) {
            minRateMap.put(columns.get(i), rates.get(i - 2).getMinString());
        }
        Map<String, String> maxRateMap = new HashMap<>();
        for (int i = 2; i < allLen; i++) {
            maxRateMap.put(columns.get(i), rates.get(i - 2).getMaxString());
        }
        data.addLast(minRateMap);
        data.addLast(maxRateMap);

        List<CommissionAmount> amount = commissionMapper.getAmount(brandId);
        if (null == amount) {
            t.setData(data);
            return t;
        }

        List<Commission> commissions = commissionMapper.selectAll(brandId);

        Map<String, List<Commission>> rowMap = ObjectUtils.listGroup(commissions, Commission::getAmountKey);

        Commission commission = new Commission();

        for (CommissionAmount commissionAmount : amount) {
            Map<String, String> row = new HashMap<>();
            row.put(ca, commissionAmount.getMinString());
            row.put(cb, commissionAmount.getMaxString());
            List<Commission> rowList = rowMap.get(commissionAmount.getKey());
            Map<String, Commission> colMap = ObjectUtils.list2map(rowList, Commission::getDiscountKey);
            for (int j = 0; j < rateLen; j++) {
                row.put(columns.get(j + 2), colMap.getOrDefault(rates.get(j).getKey(), commission).getAmountString());
            }
            data.addLast(row);
        }
        t.setData(data);
        return t;
    }

    private List<String> createColumns(int size) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            list.add("c" + i);
        }
        return list;
    }

    @Override
    @Transactional
    public int importFromExcel(MultipartFile file, Integer brandId) {
        try {
            List<Commission> commissions = readDataFromExcel(file, brandId);
            commissionMapper.clear(brandId);
            commissionMapper.insertBatch(commissions);
        } catch (IOException e) {
            throw new BusinessException(ErrorCodes.ILLEGAL_EXCEL_FORMAT);
        }
        return 0;
    }

    private List<Commission> readDataFromExcel(@NotNull MultipartFile file, Integer brandId) throws IOException {
        List<Commission> commissions = new ArrayList<>();
        InputStream inputStream = file.getInputStream();
        try {
            String fileName = file.getOriginalFilename() != null ? file.getOriginalFilename().toLowerCase() : "";
            Assert.isFalse(fileName.endsWith("xls") || fileName.endsWith("xlsx"), ErrorCodes.NOT_EXCEL_FILE);
            Workbook workBook = POIExcelHelper.getWorkBook(inputStream, fileName);
            Sheet sheet = workBook.getSheetAt(0);

            Row r1 = sheet.getRow(0);
            Row r2 = sheet.getRow(1);
            int rowSize = sheet.getPhysicalNumberOfRows();
            //tag:读取综合折扣率
            List<CommissionDiscountRate> rates = new ArrayList<>();
            int columnSize = r1.getPhysicalNumberOfCells();
            for (int i = 2; i < columnSize; i++) {
                rates.add(new CommissionDiscountRate(
                        POIExcelHelper.getCellValue(r1.getCell(i)),
                        POIExcelHelper.getCellValue(r2.getCell(i))));
            }

            //tag:读取客单金额
            for (int r = 3; r < rowSize; r++) {
                Row row = sheet.getRow(r);
                String amount = POIExcelHelper.getCellValue(row.getCell(0));
                Matcher m = p.matcher(amount);
                String minAmount = null;
                String maxAmount = null;
                if (m.matches()) {
                    String op = m.group(2);
                    switch (op) {
                        case "-": {
                            minAmount = m.group(1);
                            maxAmount = m.group(3);
                            break;
                        }
                        case ">": {
                            minAmount = m.group(3);
                            break;
                        }
                        case "<": {
                            maxAmount = m.group(3);
                        }
                    }
                }

                //合并的单元格需要
                for (int c = 2; c < columnSize; c++) {
                    CommissionDiscountRate cdr = rates.get(c - 2);
                    Commission commission = new Commission(
                            cdr.getMinString(),
                            cdr.getMaxString(),
                            minAmount,
                            maxAmount,
                            POIExcelHelper.getCellValue(row.getCell(c))
                    );
                    commission.setAmountKey(commission.createAmountKey());
                    commission.setDiscountKey(commission.createDiscountKey());
                    commission.setCreateBy(AccountHelper.getAccount().getId());
                    commission.setBrandId(brandId);
                    commissions.add(commission);
                }
            }
        } finally {
            try {
                inputStream.close();
            } catch (Exception e) {
                log.error("关闭文件流发生错误");
            }
        }

        return commissions;
    }


    @Override
    public void exportExcel(OutputStream os, Integer brandId) {
        HSSFWorkbook workbook = new HSSFWorkbook();
        try {
            CommissionTable<String> table = createReadOnlyTable(brandId);
            HSSFSheet sheet = workbook.createSheet();

            if (table == null || table.getColumns() == null || table.getData() == null) {
                //TODO:
                return;
            }
            List<? extends Map<String, String>> data = table.getData();
            List<String> columns = table.getColumns();
            int rowSize = data.size();
            int columnSize = columns.size();

            HSSFCellStyle style = style(workbook);

            HSSFCellStyle sh = style(workbook);
            sh.setFillPattern(CellStyle.SOLID_FOREGROUND);
            sh.setFillForegroundColor(HSSFColor.LIME.index);

            HSSFCellStyle s1 = style(workbook);
            s1.setFillPattern(CellStyle.SOLID_FOREGROUND);
            s1.setFillForegroundColor(HSSFColor.LIGHT_TURQUOISE.index);

            HSSFCellStyle s2 = style(workbook);
            s1.setFillPattern(CellStyle.SOLID_FOREGROUND);
            s1.setFillForegroundColor(HSSFColor.LEMON_CHIFFON.index);

            for (int r = 0; r < rowSize; r++) {
                //开始行
                HSSFRow row = sheet.createRow(r >= 2 ? r + 1 : r);
                Map<String, String> rowData = data.get(r);
                //第一行
                if (r == 0) {
                    HSSFCell c1 = row.createCell(0);
                    c1.setCellValue("综合折扣");
                    c1.setCellStyle(sh);

                    HSSFCell c2 = row.createCell(1);
                    c2.setCellValue("最低(不含)");
                    c2.setCellStyle(sh);

                    for (int c = 2; c < columnSize; c++) {
                        HSSFCell cell = row.createCell(c);
                        cell.setCellValue(rowData.getOrDefault(columns.get(c), ""));
                        cell.setCellStyle(s1);
                    }
                    continue;
                }
                //第二行
                if (r == 1) {
                    HSSFCell c1 = row.createCell(1);
                    c1.setCellValue("最高(包含)");
                    c1.setCellStyle(sh);
                    for (int c = 2; c < columnSize; c++) {
                        HSSFCell cell = row.createCell(c);
                        cell.setCellValue(rowData.getOrDefault(columns.get(c), ""));
                        cell.setCellStyle(s1);
                    }
                    continue;
                }

                //第三行
                if (r == 2) {
                    HSSFRow row2 = sheet.createRow(r);
                    HSSFCell c1 = row2.createCell(0);
                    c1.setCellValue("客单金额");
                    c1.setCellStyle(sh);
                    CellRangeAddress region1 = new CellRangeAddress(2, 2, 0, 1);
                    rangeBorder(region1, sheet, workbook);
                    sheet.addMergedRegion(region1);


                    CellRangeAddress region2 = new CellRangeAddress(2, 2, 2, columnSize - 1);
                    rangeBorder(region2, sheet, workbook);
                    sheet.addMergedRegion(region2);
                }

                for (int c = 0; c < columnSize; c++) {
                    if (c == 0) {
                        String min = rowData.getOrDefault("a", null);
                        String max = rowData.getOrDefault("b", null);

                        String cellValue = "";
                        if (null == min && null == max) {
                            cellValue = "";
                        } else if (null == min) {
                            cellValue = "<" + max;
                        } else if (null == max) {
                            cellValue = ">" + min;
                        } else {
                            cellValue = min + "-" + max;
                        }
                        HSSFCell cell = row.createCell(c);
                        cell.setCellValue(cellValue);
                        cell.setCellStyle(s1);

                        CellRangeAddress region = new CellRangeAddress(r + 1, r + 1, 0, 1);
                        sheet.addMergedRegion(region);
                        rangeBorder(region, sheet, workbook);
                        continue;
                    }
                    if (c == 1) {
                        continue;
                    }
                    HSSFCell cell = row.createCell(c);
                    cell.setCellValue(rowData.getOrDefault(columns.get(c), ""));
                    cell.setCellStyle(style);
                }
            }

            //startRow, endRow, startCol, endCol
            CellRangeAddress regionRate = new CellRangeAddress(0, 1, 0, 0);
            rangeBorder(regionRate, sheet, workbook);
            sheet.addMergedRegion(regionRate);


        } catch (Exception e) {
            log.error("导出业务员提成发生错误", e);
        } finally {
            try {
                workbook.write(os);
            } catch (IOException e) {
                log.error("关闭work book出错");
            }
            try {
                os.close();
            } catch (IOException e) {
                log.error("关闭输出流出错");
            }
        }

    }

    private void rangeBorder(CellRangeAddress cellRange, HSSFSheet sheet, HSSFWorkbook workbook) {
        POIExcelHelper.rangeBorder(cellRange, sheet, workbook);
    }

    private HSSFCellStyle hStyle(HSSFWorkbook workbook) {
        return POIExcelHelper.headerStyle(workbook);
    }

    private HSSFCellStyle style(HSSFWorkbook workbook) {
        return POIExcelHelper.style(workbook);
    }
}
